#ifndef __YESCRYPT_H__
#define __YESCRYPT_H__

#include <shadow.h>
#include <crypt.h>
#include <string>

using std::string;

namespace myNameSpace {
// 根据用户名从Linux本地/etc/shadow中获取该用户对应的密码密文（前缀+选项+盐值+哈希值）
string getEncyptedPassword(const string &userName) {
    struct spwd *pShadowPassword = getspnam(userName.c_str());
    if (!pShadowPassword) {
        perror("getspnam");
        return string();
    }
    return pShadowPassword->sp_pwdp; 
}

// 根据用户名从Linux本地/etc/shadow中获取该用户对应的前缀+选项+盐值
string getSetting(const string &userName) {
    const string encyptedPassword = getEncyptedPassword(userName);
    int count = 0; // 记录'$'出现的次数
    int idx = 0;
    for (; encyptedPassword[idx] && count != 4; ++idx) {
        if (encyptedPassword[idx] == '$') {
            ++count;
        }
    }
    return string(encyptedPassword.c_str(), idx - 1); // 返回encyptedPassword的前idx-1个字符，idx为第4个'$'所在的位置
}

// 从MD5形式的密文（前缀+盐值+哈希值）中获取setting（前缀+盐值）
// 例如：密文：$1$Fr020h1t$5VTDKry4x6N45RSLxBu.80
// setting：$1$Fr020h1t
string getMd5Setting(const string &encyptedPassword) {
    int count = 0; // 记录'$'出现的次数
    int idx = 0;
    for (; encyptedPassword[idx] && count != 3; ++idx) {
        if (encyptedPassword[idx] == '$') {
            ++count;
        }
    }
    return string(encyptedPassword.c_str(), idx - 1); // 返回encyptedPassword的前idx-1个字符，idx为第3个'$'所在的位置
}

// 生成一个MD5形式的随机setting（前缀"$1$"+length个字符长度的盐值）
string genRandomSetting(size_t length = 8) 
{
    const char *prefix = "$1$"; // MD5 加密前缀
    char output[128];
    // 使用crypt_gensalt_rn函数（线程安全版本）
    if (crypt_gensalt_rn(prefix, 0, NULL, length, output, sizeof(output)) == NULL)
    {
        perror("crypt_gensalt_rn");
        return "";
    }
    return string(output);
}
} // end of namespace myNameSpace
#endif
